using OpenTK.Graphics.OpenGL4;
using System.Drawing;
using System.Drawing.Imaging;

namespace _3Dto2D.Services;

public class TextureRenderer : IDisposable
{
    private readonly int _vao;
    private readonly int _vbo;
    private int _textureId;
    private bool _disposed;

    private static readonly float[] _vertices =
    {
        // Positions        // Texture Coords
         0.5f,  0.5f, 0.0f,  1.0f, 1.0f, // Top Right
         0.5f, -0.5f, 0.0f,  1.0f, 0.0f, // Bottom Right
        -0.5f, -0.5f, 0.0f,  0.0f, 0.0f, // Bottom Left
        -0.5f,  0.5f, 0.0f,  0.0f, 1.0f  // Top Left
    };

    public TextureRenderer()
    {
        _vbo = GL.GenBuffer();
        GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
        GL.BufferData(BufferTarget.ArrayBuffer, _vertices.Length * sizeof(float), _vertices, BufferUsageHint.StaticDraw);

        _vao = GL.GenVertexArray();
        GL.BindVertexArray(_vao);

        // Position attribute
        GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
        GL.EnableVertexAttribArray(0);

        // Texture coord attribute
        GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
        GL.EnableVertexAttribArray(1);

        _textureId = -1;
    }

    public void LoadTexture(Bitmap image)
    {
        if (_textureId != -1)
        {
            GL.DeleteTexture(_textureId);
        }

        _textureId = GL.GenTexture();
        GL.BindTexture(TextureTarget.Texture2D, _textureId);

        BitmapData data = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
            ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, data.Width, data.Height, 0,
            OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);

        image.UnlockBits(data);

        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
        GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
    }

    public void Render()
    {
        if (_textureId == -1) return;

        GL.BindTexture(TextureTarget.Texture2D, _textureId);
        GL.BindVertexArray(_vao);
        GL.DrawArrays(PrimitiveType.TriangleFan, 0, 4);
    }

    public void Dispose()
    {
        if (_disposed) return;
        GL.DeleteBuffer(_vbo);
        GL.DeleteVertexArray(_vao);
        if (_textureId != -1) GL.DeleteTexture(_textureId);
        _disposed = true;
    }
}

